﻿using System.Linq;
using FitnessCenter.Common.Constants;
using FitnessCenter.Common.Extesions;
using FitnessCenter.DataAccessLayer.DataModels;
using FitnessCenter.DataAccessLayer.Repositories.Interfaces;
using FitnessCenter.WpfApp.Events;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.PubSubEvents;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows.Input;

namespace FitnessCenter.WpfApp.ViewModels
{
    public class PersonViewModel : BaseViewModel
    {
        private readonly IPersonRepository _personRepository;

        #region Properties

        private ObservableCollection<Person> _visitors;
        public ObservableCollection<Person> Visitors
        {
            get { return _visitors; }
            set
            {
                if (_visitors != value)
                {
                    _visitors = value;
                    OnPropertyChanged();
                }
            }
        }

        private Person _selectedVisitor;
        public Person SelectedVisitor
        {
            get { return _selectedVisitor; }
            set
            {
                if (_selectedVisitor != value)
                {
                    _selectedVisitor = value;
                    OnPropertyChanged();
                }
            }
        }

        #region Details labels

        private string _returnLabel;
        public string ReturnLabel
        {
            get { return _returnLabel; }
            set
            {
                if (_returnLabel != value)
                {
                    _returnLabel = value;
                    OnPropertyChanged();
                }
            }
        }

        private string _firstNameLabel;
        public string FirstNameLabel
        {
            get { return _firstNameLabel; }
            set
            {
                if (_firstNameLabel != value)
                {
                    _firstNameLabel = value;
                    OnPropertyChanged();
                }
            }
        }

        private string _lastNameLabel;
        public string LastNameLabel
        {
            get { return _lastNameLabel; }
            set
            {
                if (_lastNameLabel != value)
                {
                    _lastNameLabel = value;
                    OnPropertyChanged();
                }
            }
        }
        #endregion

        private bool _isReadonly;
        public bool IsReadonly
        {
            get { return _isReadonly; }
            set
            {
                if (_isReadonly != value)
                {
                    _isReadonly = value;
                    OnPropertyChanged();
                }
            }
        }

        #region Buttons labels

        private string _editLabel;
        public string EditLabel
        {
            get { return _editLabel; }
            set
            {
                if (_editLabel != value)
                {
                    _editLabel = value;
                    OnPropertyChanged();
                }
            }
        }

        private string _newLabel;
        public string NewLabel
        {
            get { return _newLabel; }
            set
            {
                if (_newLabel != value)
                {
                    _newLabel = value;
                    OnPropertyChanged();
                }
            }
        }

        private string _deleteLabel;
        public string DeleteLabel
        {
            get { return _deleteLabel; }
            set
            {
                if (_deleteLabel != value)
                {
                    _deleteLabel = value;
                    OnPropertyChanged();
                }
            }
        }

        private string _saveLabel;
        public string SaveLabel
        {
            get { return _saveLabel; }
            set
            {
                if (_saveLabel != value)
                {
                    _saveLabel = value;
                    OnPropertyChanged();
                }
            }
        }

        private string _cancelLabel;
        public string CancelLabel
        {
            get { return _cancelLabel; }
            set
            {
                if (_cancelLabel != value)
                {
                    _cancelLabel = value;
                    OnPropertyChanged();
                }
            }
        }
        #endregion

        #region Buttons visibilities

        private bool _isNewVisible;
        public bool IsNewVisible
        {
            get { return _isNewVisible; }
            set
            {
                if (_isNewVisible != value)
                {
                    _isNewVisible = value;
                    OnPropertyChanged();
                }
            }
        }

        private bool _isEditVisible;
        public bool IsEditVisible
        {
            get { return _isEditVisible; }
            set
            {
                if (_isEditVisible != value)
                {
                    _isEditVisible = value;
                    OnPropertyChanged();
                }
            }
        }
        
        private bool _isDeleteVisible;
        public bool IsDeleteVisible
        {
            get { return _isDeleteVisible; }
            set
            {
                if (_isDeleteVisible != value)
                {
                    _isDeleteVisible = value;
                    OnPropertyChanged();
                }
            }
        }

        private bool _isSaveVisible;
        public bool IsSaveVisible
        {
            get { return _isSaveVisible; }
            set
            {
                if (_isSaveVisible != value)
                {
                    _isSaveVisible = value;
                    OnPropertyChanged();
                }
            }
        }

        private bool _isCancelVisible;
        public bool IsCancelVisible
        {
            get { return _isCancelVisible; }
            set
            {
                if (_isCancelVisible != value)
                {
                    _isCancelVisible = value;
                    OnPropertyChanged();
                }
            }
        }
        #endregion
        #endregion

        #region Commands

        public ICommand ReturnToDashboardCommand { get { return new DelegateCommand(OnReturnToDashboard); } }
        public ICommand SaveVisitorCommand { get { return new DelegateCommand(OnSave); } }
        public ICommand AddNewVisitorCommand { get { return new DelegateCommand(OnNewVisitor); } }
        public ICommand EditVisitorCommand { get { return new DelegateCommand(OnEdit); } }
        public ICommand DeleteVisitorCommand { get { return new DelegateCommand(OnDelete); } }
        public ICommand CancelCommand { get { return new DelegateCommand(OnCancel); } }
        #endregion

        public PersonViewModel
            (
                IEventAggregator eventAggregator,
                IPersonRepository personRepository
            ) : base(eventAggregator)
        {
            _personRepository = personRepository;
            Load();
        }

        #region Methods

        private void Load()
        {
            SetLabels();
            SetViewOptions();

            LoadVisitors();
        }

        private void LoadVisitors()
        {
            Visitors = _personRepository.GetVisitors().AsObservable();
        }

        private void SetLabels()
        {
            ReturnLabel = Phrases.ReturnToDashboard;

            FirstNameLabel = "First Name:";
            LastNameLabel = "Last Name:";

            NewLabel = Phrases.New;
            EditLabel = Phrases.Edit;
            DeleteLabel = Phrases.Delete;
            SaveLabel = Phrases.Save;
            CancelLabel = Phrases.Cancel;
        }

        private void SetViewOptions()
        {
            IsReadonly = true;

            IsEditVisible = IsNewVisible = IsDeleteVisible = true;
            IsSaveVisible = IsCancelVisible = false;
        }

        private void SetEditOptions()
        {
            IsReadonly = false;

            IsEditVisible = IsNewVisible = IsDeleteVisible = false;
            IsSaveVisible = IsCancelVisible = true;
        }
        #endregion

        #region Command handlers

        private void OnReturnToDashboard()
        {
            EventAggregator.GetEvent<SelectModuleEvent>().Publish(ModuleNames.DashboardModule);
        }

        private void OnSave()
        {
            SetViewOptions();

            _personRepository.Save(SelectedVisitor);
            SelectedVisitor = null;

            LoadVisitors();
        }

        private void OnEdit()
        {
            SetEditOptions();
            _personRepository.Save(SelectedVisitor);
        }

        private void OnDelete()
        {
            if(!Visitors.Any())
                return;

            _personRepository.Delete(SelectedVisitor);
            LoadVisitors();
        }

        private void OnNewVisitor()
        {
            SetEditOptions();
            SelectedVisitor = new Person();
        }

        private void OnCancel()
        {
            SetViewOptions();
            SelectedVisitor = Visitors.FirstOrDefault() ?? new Person();
        }
        #endregion
    }
}
